'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

/**
 * 将数组（array）拆分成多个 size 长度的区块，并将这些区块组成一个新数组。
 * 如果array 无法被分割成全部等长的区块，那么最后剩余的元素将组成一个区块。
 * @param {Array} array - 需要处理的数组
 * @param {number} size - 每个数组区块的长度
 * @returns {Array[]} 返回一个包含拆分区块的新数组（注：相当于一个二维数组）。
 * @example
 * chunk([1, 2, 3, 4, 5], 2);
 * // => [[1, 2], [3, 4], [5]]
 */
function chunk(array, size = 1) {
    let result = [];
    for (let i = 0; i < array.length; i += size) {
        result.push(array.slice(i, i + size));
    }
    return result;
}

/**
 * 创建一个新数组，包含原数组中所有的非假值元素。
 * 例如false, null,0, "", undefined, 和 NaN 都是被认为是“假值”。
 * @param {Array} array - 待处理的数组
 * @returns {Array} 返回过滤掉假值的新数组。
 * @example
 * compact([0, 1, false, 2, '', 3]);
 * // => [1, 2, 3]
 */
function compact(array) {
    return array.filter(item => item);
}

/**
 * 创建一个新数组，将array与任何数组 或 值连接在一起。
 * @param {Array} array - 被连接的数组。
 * @param  {...any} values - 连接的值。
 * @return {Array} 返回连接后的新数组。
 * @example
 * var array = [1];
 * var other = concat(array, 2, [3], [[4]]);
 * console.log(other);
 * // => [1, 2, 3, [4]]
 * console.log(array);
 * // => [1]
 */
function concat(array, ...values) {
    return array.concat(...values);
}

/**
 * 对象继承
 */
const extend = Object.assign;
/**
 * 判断是否为对象类型
 * @param val - 需要判断的值
 * @returns 返回 true 或 false
 */
const isObject = (val) => {
    return val != null && typeof val === 'object';
};
/**
 * 判断是否是 undefined
 * @param val - 需要判断的值
 * @returns 返回 true 或 false
 */
const isUndefined = (val) => typeof val === 'undefined';
/**
 * 判断是否为 NaN
 * @param val - 需要判断的值
 * @returns 返回 true 或 false
 */
const isNaN = (val) => val !== val;
/**
 * 判断是否为数组
 */
const isArray = Array.isArray;
/**
 * 判断是否为字符串类型
 * @param value - 需要判断的值
 * @returns 返回 true 或 false
 */
const isString = (value) => typeof value === 'string';
/**
 * 判断是否为 function 类型
 * @param value - 需要判断的值
 * @returns 返回 true 或 false
 */
const isFunction = (value) => typeof value === 'function';
/**
 * 比较两个值是否发生了变化
 * @param Value - 原始值
 * @param newValue - 新值
 * @returns 返回 true 或 false
 */
const hasChanged = (Value, newValue) => {
    return !Object.is(Value, newValue);
};
/**
 * 检查一个对象是否直接拥有某个属性
 * @param val - 需要判断的对象
 * @param key - 需要判断的属性
 * @returns 返回 true 或 false
 */
const hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key);

var index$5 = /*#__PURE__*/Object.freeze({
    __proto__: null,
    extend: extend,
    isObject: isObject,
    isUndefined: isUndefined,
    isNaN: isNaN,
    isArray: isArray,
    isString: isString,
    isFunction: isFunction,
    hasChanged: hasChanged,
    hasOwn: hasOwn
});

/**
 * 创建一个具有唯一array值的数组，每个值不包含在其他给定的数组中。
 * （注：即创建一个新数组，这个数组中的值，为第一个数字（array 参数）排除了给定数组中的值。）
 * 该方法使用SameValueZero做相等比较。结果值的顺序是由第一个数组中的顺序确定。
 * @param array - 要检查的数组。
 * @param values - 排除的值。
 * @returns 返回一个过滤值后的新数组。
 * @example
 * difference([3, 2, 1], [4, 2]);
 * // => [3, 1]
 */
function difference(array, values) {
    if (!isArray(array) || !isArray(values))
        return [];
    const valuesSet = new Set(values);
    let hasNaN = false;
    for (const value of values) {
        if (isNaN(value)) {
            hasNaN = true;
            break;
        }
    }
    return array.filter(item => {
        if (isNaN(item))
            return !hasNaN;
        return !valuesSet.has(item);
    });
}
/**
 * 这个方法类似_.difference ，除了它接受一个 iteratee （注：迭代器）， 调用array 和 values 中的每个元素以产生比较的标准。
 * 结果值是从第一数组中选择。iteratee 会调用一个参数：(value)。（注：首先使用迭代器分别迭代array 和 values中的每个元素，返回的值作为比较值）。
 * @param array - 要检查的数组。
 * @param values - 排除的值。
 * @returns 返回一个过滤值后的新数组。
 * @example
 * differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
 * // => [3.1, 1.3]
 * The `_.property` iteratee shorthand.
 * differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
 * // => [{ 'x': 2 }]
 */
function differenceBy(array, values, identity) {
    if (!array)
        return [];
    const getValue = (item) => {
        if (isFunction(identity))
            return identity(item);
        else if (isString(identity))
            return item[identity];
        return item;
    };
    const valuesSet = new Set();
    for (const value of values) {
        valuesSet.add(getValue(value));
    }
    return array.filter(item => !valuesSet.has(getValue(item)));
}
/**
 * 这个方法类似_.difference ，除了它接受一个 comparator （注：比较器），它调用比较array，values中的元素。
 * 结果值是从第一数组中选择。comparator 调用参数有两个：(arrVal, othVal)。
 * @param array - 要检查的数组。
 * @param values - 排除的值。
 * @param comparator - comparator 调用每个元素。
 * @returns 返回一个过滤值后的新数组。
 * @example
 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
 * differenceWith(objects, [{ 'x': 1, 'y': 2 }], isEqual);
 * // => [{ 'x': 2, 'y': 1 }]
 */
function differenceWith(array, values, comparator) {
    if (!isArray(array))
        return [];
    if (!isArray(values) || !isFunction(comparator))
        return array.slice();
    return array.filter(arrItem => {
        return !values.some(valueItem => comparator(arrItem, valueItem));
    });
}

var index$4 = /*#__PURE__*/Object.freeze({
    __proto__: null,
    chunk: chunk,
    compact: compact,
    concat: concat,
    difference: difference,
    differenceBy: differenceBy,
    differenceWith: differenceWith
});

/**
 * 执行深比较来确定两者的值是否相等。
 * 注意: 这个方法支持比较 arrays, array buffers, booleans, date objects, error objects, maps, numbers, Object objects, regexes, sets, strings, symbols, 以及 typed arrays. Object 对象值比较自身的属性，不包括继承的和可枚举的属性。 不支持函数和DOM节点比较。
 * @param value - 用来比较的值。
 * @param other - 另一个用来比较的值。
 * @return 如果 两个值完全相同，那么返回 true，否则返回 false。
 * @example
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 * isEqual(object, other);
 * // => true
 * object === other;
 * // => false
 */
function isEqual(value, other) {
    // 如果两个值严格相等，直接返回true
    if (value === other)
        return true;
    // 处理null和undefined的情况
    if (value == null || other == null) {
        return value === other;
    }
    // 比较Date对象
    if (value instanceof Date && other instanceof Date) {
        return value.getTime() === other.getTime();
    }
    // 比较正则表达式
    if (value instanceof RegExp && other instanceof RegExp) {
        return value.toString() === other.toString();
    }
    // 比较ArrayBuffer
    if (value instanceof ArrayBuffer && other instanceof ArrayBuffer) {
        if (value.byteLength !== other.byteLength)
            return false;
        const view1 = new DataView(value);
        const view2 = new DataView(other);
        for (let i = 0; i < value.byteLength; i++) {
            if (view1.getUint8(i) !== view2.getUint8(i))
                return false;
        }
        return true;
    }
    // 比较TypedArray (Uint8Array, Int32Array等)
    if (ArrayBuffer.isView(value) && ArrayBuffer.isView(other)) {
        if (value.constructor !== other.constructor)
            return false;
        if (value.byteLength !== other.byteLength)
            return false;
        const view1 = new DataView(value.buffer, value.byteOffset, value.byteLength);
        const view2 = new DataView(other.buffer, other.byteOffset, other.byteLength);
        for (let i = 0; i < value.byteLength; i++) {
            if (view1.getUint8(i) !== view2.getUint8(i))
                return false;
        }
        return true;
    }
    // 比较Map
    if (value instanceof Map && other instanceof Map) {
        if (value.size !== other.size)
            return false;
        for (const [key, val] of value) {
            if (!other.has(key))
                return false;
            if (!isEqual(val, other.get(key)))
                return false;
        }
        return true;
    }
    // 比较Set
    if (value instanceof Set && other instanceof Set) {
        if (value.size !== other.size)
            return false;
        for (const val of value) {
            if (!other.has(val))
                return false;
        }
        return true;
    }
    // 比较Error对象
    if (value instanceof Error && other instanceof Error) {
        return value.message === other.message && value.name === other.name;
    }
    // 比较Symbol
    if (typeof value === 'symbol' && typeof other === 'symbol') {
        return value.toString() === other.toString();
    }
    // 比较数组
    if (Array.isArray(value) && Array.isArray(other)) {
        if (value.length !== other.length)
            return false;
        for (let i = 0; i < value.length; i++) {
            if (!isEqual(value[i], other[i]))
                return false;
        }
        return true;
    }
    // 比较对象
    if (typeof value === 'object' && typeof other === 'object') {
        const valueKeys = Object.keys(value);
        const otherKeys = Object.keys(other);
        if (valueKeys.length !== otherKeys.length)
            return false;
        for (const key of valueKeys) {
            if (!other.hasOwnProperty(key))
                return false;
            if (!isEqual(value[key], other[key]))
                return false;
        }
        return true;
    }
    return false;
}

/**
 * 如果 value 不是数组, 那么强制转为数组。
 * @param value - 要处理的值。
 * @returns 返回转换后的数组。
 * @example
 * _.castArray(1);
 * // => [1]
 * _.castArray([1, 2, 3]);
 * // => [1, 2, 3]
 * _.castArray('abc');
 * // => ['abc']
 * _.castArray(null);
 * // => [null]
 * _.castArray(undefined);
 * // => [undefined]
 * const array = [1, 2, 3]
 * castArray(array) === array
 * // => true
 */
function castArray(value) {
    // 没有传任何参数的情况（包括没有传undefined、null）
    if (arguments.length === 0)
        return [];
    return isArray(value) ? value : [value];
}

/**
 * 创建一个 value 的浅拷贝。
 * @param value - 要拷贝的值
 * @returns 返回拷贝后的值。
 * @example
 * const objects = [{ 'a': 1 }, { 'b': 2 }];
 * const shallow = clone(objects);
 * shallow[0] === objects[0]
 * // => true
 */
function clone(value) {
    if (isArray(value)) {
        return [...value];
    }
    if (isObject(value)) {
        return Object.assign({}, value);
    }
    return value;
}
/**
 * 这个方法类似 clone，除了它会递归拷贝 value。（注：也叫深拷贝）。
 * @param value - 要深拷贝的值。
 * @return 返回拷贝后的值。
 * @example
 * const objects = [{ 'a': 1 }, { 'b': 2 }];
 * const deep = cloneDeep(objects);
 * deep[0] === objects[0]
 * // => false
 */
function cloneDeep(value) {
    if (!isObject(value))
        return value;
    if (isArray(value)) {
        return value.map(item => cloneDeep(item));
    }
    if (isObject(value)) {
        const result = {};
        for (const key in value) {
            if (value.hasOwnProperty(key)) {
                result[key] = cloneDeep(value[key]);
            }
        }
        return result;
    }
    return value;
}
/**
 * 这个方法类似 clone，除此之外它还接收一个 customizer 回调函数，定制返回的克隆值。
 * 如果 customizer 返回 undefined 将会使用拷贝方法代替处理。
 * @param value - 用来递归克隆的值。
 * @param customizer - 自定义克隆的函数。
 * @returns 返回克隆值。
 * @example
 * const object = { a: 1, b: 2 };
 * const cloned = cloneWith(object, (value) => {
 *   if (value === 1) {
 *       return 100;
 *   }
 * });
 * // => { a: 100, b: 2 };
 */
function cloneWith(value, customizer) {
    if (!isObject(value))
        return value;
    if (!customizer || !isFunction(customizer))
        return clone(value);
    if (isArray(value)) {
        return value.map(val => {
            const customizerRes = customizer(val);
            return isUndefined(customizerRes)
                ? val
                : customizerRes;
        });
    }
    if (isObject(value)) {
        const result = {};
        for (const key in value) {
            const val = value[key];
            const customizerRes = customizer(val);
            result[key] = isUndefined(customizerRes)
                ? val
                : customizerRes;
        }
        return result;
    }
    return value;
}
/**
 * 这个方法类似 cloneWith，除了它会递归克隆 value。
 * @param value - 用来递归克隆的值。
 * @param customizer - 自定义克隆的函数。
 * @returns 返回克隆值。
 * @example
 * const object = { a: { c: 1 }, b: 2 };
 * const cloned = cloneWith(object, (value) => {
 *   if (value === 1) {
 *       return 100;
 *   }
 * });
 * // => { a: { c: 100 }, b: 2 }
 */
function cloneDeepWith(value, customizer) {
    if (!isObject(value))
        return value;
    if (!customizer || !isFunction(customizer))
        return cloneDeep(value);
    if (isArray(value)) {
        return value.map(val => {
            const customizerRes = customizer(val);
            return isUndefined(customizerRes)
                ? cloneDeepWith(val, customizer)
                : customizerRes;
        });
    }
    if (isObject(value)) {
        const result = {};
        for (const key in value) {
            const val = value[key];
            const customizerRes = customizer(val);
            result[key] = isUndefined(customizerRes)
                ? cloneDeepWith(val, customizer)
                : customizerRes;
        }
        return result;
    }
    return value;
}

/**
 * 转换 value 为一个数组。
 * @param value - 要转换的值。
 * @returns 返回转换后的数组。
 * @example
 * toArray('abc')           // ['a', 'b', 'c']
 * toArray(1)               // []
 * toArray({a: 1, b: 2})    // [1, 2]
 * toArray([1, 2])          // [1, 2]
 */
function toArray(value) {
    if (isArray(value))
        return value;
    if (value === null || value === undefined)
        return [];
    if (typeof value === 'string')
        return value.split('');
    if (typeof value === 'object')
        return Object.keys(value).map(key => value[key]);
    return [];
}

var index$3 = /*#__PURE__*/Object.freeze({
    __proto__: null,
    isEqual: isEqual,
    castArray: castArray,
    clone: clone,
    cloneDeep: cloneDeep,
    cloneWith: cloneWith,
    cloneDeepWith: cloneDeepWith,
    toArray: toArray
});

/**
 * 分配来源对象的可枚举属性到目标对象上。
 * 来源对象的应用规则是从左到右，随后的下一个对象的属性会覆盖上一个对象的属性。
 * @param target - 要合并的对象。
 * @param sources - 要合并的对象。
 * @returns 返回合并后的对象。
 * @example
 * function Foo() {
 *   this.a = 1;
 * }
 * function Bar() {
 *   this.c = 3;
 * }
 * Foo.prototype.b = 2;
 * Bar.prototype.d = 4;
 * assign({ 'a': 0 }, new Foo, new Bar);
 * // => { 'a': 1, 'c': 3 }
 */
function assign(target, ...sources) {
    if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object');
    }
    // 处理原始值包装对象
    target = Object(target);
    for (const source of sources) {
        if (source == null)
            continue;
        // 复制所有可枚举的自有属性
        for (const key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                target[key] = source[key];
            }
        }
        // 复制Symbol属性
        const symbols = Object.getOwnPropertySymbols(source);
        for (const symbol of symbols) {
            target[symbol] = source[symbol];
        }
    }
    return target;
}

var index$2 = /*#__PURE__*/Object.freeze({
    __proto__: null,
    assign: assign
});

/**
 * 创建一个只能调用 func 一次的函数。重复调用返回第一次调用的结果。
 * func 调用时，this 绑定到创建的函数，并传入对应参数。
 * @param func 指定的触发的函数。
 * @returns 返回新的受限函数。
 * @example
 * const initialize = once(createApplication);
 * initialize();
 * initialize(); // => 第二次调用不会执行createApplication，而是返回第一次的结果
 */
function once(func) {
    if (typeof func !== 'function') {
        throw new TypeError('Expected a function');
    }
    let called = false;
    let result;
    return function (...args) {
        if (!called) {
            called = true;
            result = func.apply(this, args);
        }
        return result;
    };
}

/**
 * 创建一个函数，调用func时参数为相对应的transforms的返回值。
 * @param func - 要包裹的函数。
 * @param transforms - 一个函数数组，每个函数的返回值将作为func的参数。
 * @returns 返回新函数。
 * @example
 * const func = (x: number, y: number) => [x, y]
 * const add = (a: number) => a + 1
 * const square = (a: number) => a * a
 * const composedFunc = overArgs(func, [add, square])
 * composedFunc(3, 4) // [4, 16]
 */
function overArgs(func, transforms) {
    if (transforms.length === 0)
        return func;
    return (...args) => {
        const nextArgs = args.map((arg, i) => transforms[i](arg));
        return func(...nextArgs);
    };
}

/**
 * 创建一个函数。 该函数调用 func，并传入预设的 partials 参数。 这个方法类似_.bind，除了它不会绑定 this。
 * @param func - 需要预设的函数
 * @param partials - 预设的参数
 * @returns 返回预设参数的函数。
 * @example
 * const greet = (greeting, name) => `${greeting} ${name}!`;
 * const sayHello = partial(greet, 'Hello');
 * sayHello('John'); // => 'Hello John!'
 */
function partial(func, ...partials) {
    return (params) => {
        return func(...partials, params);
    };
}

/**
 * 创建一个 debounced（防抖动）函数，该函数会从上一次被调用后，延迟 wait 毫秒后调用 func 方法。
 * debounced（防抖动）函数提供一个 cancel 方法取消延迟的函数调用以及 flush 方法立即调用。
 * @param func - 需要防抖处理的函数。
 * @param wait - 需要延迟的毫秒数。
 * @returns 返回新的 debounced（防抖动）函数。
 */
function debounce(func, wait) {
    let timeoutId = null;
    let lastArgs;
    let lastThis;
    // 清除定时器
    function clearTimer() {
        if (timeoutId) {
            clearTimeout(timeoutId);
            timeoutId = null;
        }
    }
    // 延迟执行函数
    function delayed() {
        clearTimer();
        func.apply(lastThis, lastArgs);
    }
    // 返回的防抖函数
    function debounced(...args) {
        lastArgs = args;
        lastThis = this;
        clearTimer();
        timeoutId = setTimeout(delayed, wait);
    }
    // 添加取消方法
    debounced.cancel = function () {
        clearTimer();
    };
    return debounced;
}

/**
 * 创建一个函数，调用func时候接收翻转的参数。
 * @param func - 要翻转参数的函数。
 * @returns 返回一个新的函数。
 * @example
 * const flipped = flip(function() {
 *   return toArray(arguments)
 * })
 * const result = flipped(1, 2, 3)
 * // => [3, 2, 1]
 */
function flip(func) {
    return function (...args) {
        return func.apply(this, args.reverse());
    };
}

var index$1 = /*#__PURE__*/Object.freeze({
    __proto__: null,
    once: once,
    overArgs: overArgs,
    partial: partial,
    debounce: debounce,
    flip: flip
});

/**
 * 两个数相加。
 * @param augend - 相加的第一个数。
 * @param addend - 相加的第二个数。
 * @returns 返回总和。
 * @example
 * add(6, 4); // => 10
 */
function add(augend, addend) {
    return Number(augend) + Number(addend);
}

/**
 * 根据 precision（精度） 向上舍入 number。（注： precision（精度）可以理解为保留几位小数。）
 * @param number - 要向上舍入的值。
 * @param precision - 向上舍入的的精度。
 * @returns 返回向上舍入的值。
 * @example
 * ceil(4.006); // => 5
 * ceil(4.004, 2); // => 4.01
 * ceil(6040, -2); // => 6100
 */
function ceil(number, precision = 0) {
    if (typeof number !== 'number' || typeof precision !== 'number') {
        return NaN;
    }
    if (precision === 0) {
        return Math.ceil(number); // 向上取整
    }
    // 计算精度因子
    const factor = Math.pow(10, precision);
    // 向上取整计算
    const result = Math.ceil(number * factor) / factor;
    // Number.MAX_SAFE_INTEGER 是 JavaScript 中的一个重要常量，它表示在 JavaScript 中能够精确表示的最大安全整数。
    // 使用Number.EPSILON进行微调
    return Math.abs(result) < Number.MAX_SAFE_INTEGER
        ? (result + Number.EPSILON)
        : result;
}

/**
 * 安全的两数相除函数
 * @param dividend - 被除数
 * @param divisor - 除数
 * @param precision - 保留小数位数（默认不处理）
 * @returns 返回商数，如果除数为0则返回Infinity或-Infinity
 * @throws 如果参数不是有效数字会抛出TypeError
 *
 * @example
 * divide(10, 3);     // 3.3333333333333335
 * divide(10, 3, 2);  // 3.33
 * divide(10, 0);     // Infinity
 * divide(-10, 0);    // -Infinity
 */
function divide(dividend, divisor, precision) {
    if (typeof dividend !== 'number' || typeof divisor !== 'number') {
        throw new TypeError('Both dividend and divisor must be numbers');
    }
    if (divisor === 0) {
        return dividend === 0 ? NaN : (dividend > 0 ? Infinity : -Infinity);
    }
    let result = dividend / divisor;
    // 处理精度
    if (typeof precision === 'number' && precision >= 0) {
        const factor = 10 ** precision;
        result = Math.round(result * factor) / factor;
        if (Math.abs(result) < Number.MAX_SAFE_INTEGER) {
            result = Number(result.toFixed(precision));
        }
    }
    return result;
}

var index = /*#__PURE__*/Object.freeze({
    __proto__: null,
    add: add,
    ceil: ceil,
    divide: divide
});

exports.array = index$4;
exports["function"] = index$1;
exports.language = index$3;
exports.math = index;
exports.object = index$2;
exports.shared = index$5;
